package com.jt.www.admin.order_wxb.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jt.www.admin.order_wxb.service.BatchInsService;
import com.jt.www.admin.pay.service.PayCertService;
import com.jt.www.admin.user.service.RegisterCustomerService;
import com.jt.www.dao.mapper.woxuebao.AreaInfoEntityMapper;
import com.jt.www.dao.mapper.woxuebao.InsBatchEntityMapper;
import com.jt.www.domain.enums.common.IsOrNotEnum;
import com.jt.www.domain.enums.common.RelationshipEnum;
import com.jt.www.domain.enums.pc.MarketerChannelCodeEnum;
import com.jt.www.domain.qo.ConfirmPolicyQo;
import com.jt.www.enums.endorse.CertificateTypeForCaseEnum;
import com.jt.www.enums.extend.SchoolTypeEnum;
import com.jt.www.enums.woxuebao.*;
import com.jt.www.model.registerCustomer.vo.ManagerInfoVo;
import com.jt.www.model.reps.GenericDataResponse;
import com.jt.www.model.reps.GenericListResponse;
import com.jt.www.model.reps.GenericResponse;
import com.jt.www.model.reps.ResponseData;
import com.jt.www.model.vo.endorse.ExcelFileDetailVo;
import com.jt.www.model.vo.woxuebao.*;
import com.jt.www.model.woxuebao.AreaInfoEntity;
import com.jt.www.model.woxuebao.InsBatchEntity;
import com.jt.www.model.woxuebao.Risk.ContextRiskMap;
import com.jt.www.model.woxuebao.Risk.RiskResponseEntity;
import com.jt.www.model.woxuebao.toubao.*;
import com.jt.www.remote.ParserClient;
import com.jt.www.remote.UserClient;
import com.jt.www.remote.ins.InsClient;
import com.jt.www.remote.woxuebao.InsOrderClient;
import com.jt.www.util.ChangeUtils;
import com.jt.www.util.DateUtils;
import com.jt.www.util.JsonUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.WeekendCriteria;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author admin_ltf
 * @create 2019-06-05 11:28
 */
@Service
public class BatchInsServiceImpl implements BatchInsService {

    public static final Logger log = LoggerFactory.getLogger(BatchInsServiceImpl.class);

    @Autowired
    ParserClient parserClient;
    @Autowired
    InsBatchEntityMapper insBatchEntityMapper;
    @Autowired
    InsOrderClient insOrderClient;
    @Autowired
    AreaInfoEntityMapper areaInfoEntityMapper;
    @Autowired
    UserClient userClient;
    @Autowired
    PayCertService payCertService;
    @Autowired
    InsClient insClient;
    @Autowired
    RegisterCustomerService registerCustomerService;
    @Autowired
    private WxbService wxbService;

    /**
     * 计算保险天数：根据时间秒毫秒数判断两个时间的间隔
     *
     * @param end
     * @param start
     * @return
     */
    public static int calculatedDays(String end, String start) {
        int days = 0;
        try {
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date1 = sf.parse(end);
            Date date2 = sf.parse(start);
            double d1 = date1.getTime() - date2.getTime();
            double d2 = (1000 * 3600 * 24);
            Double ceil = Math.ceil(d1 / d2);
            days = ceil.intValue();
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return days;
    }

    public ResponseEntity batchIns(BatchInsParamVO batchInsParam) throws Exception {
        String findCode = "batchIns_" + System.currentTimeMillis();
        //读出全部的地区配置信息， 后期可以优化到utils中 使用容器启动后静态加载一次
        //最后会让前端把相关的地区相关参数传过来
//        Map<String,String> regionMap = createAreaDate();

        // 首先根据 fileId  调远程接口  查询数据，然后遍历结果，入库  入库要加状态
        ResponseEntity<GenericListResponse<ExcelFileDetailVo>> parserRes;
        try {
            parserRes = parserClient.excelDetailList(batchInsParam.getFileId(), null, 1, 2000);
        } catch (Exception e) {
            return GenericDataResponse.errorWithMsg("调用清单服务异常!");
        }
        List<ExcelFileDetailVo> list = parserRes.getBody().getList();
        if (CollectionUtils.isEmpty(parserRes.getBody().getList())) {
            return GenericDataResponse.errorWithMsg("清单内容为空!");
        }
        log.info("{}查询到数据记录数：{}", findCode, list.size());
        List<InsBatchEntity> insBatchEntityList = Lists.newArrayList();
        for (ExcelFileDetailVo excelFileDetailVo : list) {
            InsBatchEntity insBatchEntity = createInsBatchEntity(findCode, excelFileDetailVo.getContent(), batchInsParam);
            insBatchEntityList.add(insBatchEntity);
        }
        //保存
        insBatchEntityMapper.insertList(insBatchEntityList);
//        //保存后直接发送
//        sendMessageToIns(insBatchEntityList);

        return GenericDataResponse.ok();
    }

    /**
     * 生成批量业务表数据
     *
     * @param findCode
     * @param content
     * @param batchInsParam
     * @param regionMap
     * @return
     */
    private InsBatchEntity createInsBatchEntity(String findCode, String content, BatchInsParamVO batchInsParam) {
        InsBatchEntity insBatchEntity = JsonUtils.fromJson(content, InsBatchEntity.class);
        String proCode = batchInsParam.getName();
        insBatchEntity.setProCode(proCode);
        insBatchEntity.setProName(ProNameToCodeEnum.getproductName(proCode));
        insBatchEntity.setProGram(batchInsParam.getLevel());
        insBatchEntity.setProLevel(ProgramToLevelEnum.getprodLevel(batchInsParam.getLevel()));
        insBatchEntity.setProType(batchInsParam.getType());
        insBatchEntity.setStartYear(batchInsParam.getStartYear());
        insBatchEntity.setEndYear(batchInsParam.getEndYear());
        insBatchEntity.setInsYear(batchInsParam.getYear());
        insBatchEntity.setUserCode(batchInsParam.getUserCode());
        insBatchEntity.setTbTime(new Date());
        insBatchEntity.setSchoolProvName(batchInsParam.getSchoolProvName());
        insBatchEntity.setSchoolProvCode(batchInsParam.getSchoolProvCode());
        insBatchEntity.setSchoolCityName(batchInsParam.getSchoolCityName());
        insBatchEntity.setSchoolCityCode(batchInsParam.getSchoolCityCode());
        insBatchEntity.setSchoolAreaName(batchInsParam.getSchoolAreaName());
        insBatchEntity.setSchoolAreaCode(batchInsParam.getSchoolAreaCode());
        insBatchEntity.setCreateTime(new Date());
        insBatchEntity.setUpdateTime(new Date());
        String policySex = "男".equals(insBatchEntity.getPolicySex()) ? "0" : "1";
        insBatchEntity.setPolicySex(policySex);
        String insuredSex = "男".equals(insBatchEntity.getInsuredSex()) ? "0" : "1";
        insBatchEntity.setInsuredSex(insuredSex);
        insBatchEntity.setResId(batchInsParam.getResId());
        insBatchEntity.setResName(batchInsParam.getResName());
        insBatchEntity.setIsDeleted(IsOrNotEnum.NO.getValue());
        String insuredPolicyRel = insBatchEntity.getInsuredPolicyRel();
        insBatchEntity.setInsuredPolicyRel(RelationshipEnum.getCodeByDesc(insuredPolicyRel));
//                ProgramToLevelEnum
        // cardType_0身份证,1护照,2军人证（军官证）,3户口本,4出生证,5士兵证,6临时身份证,
        // 7台湾居民来往大陆通行证,8港澳居民来往内地通行证,9驾驶执照,10返乡证,11其它
        String policyCardType = CertificateTypeForCaseEnum.getCaseCodeByMsg(insBatchEntity.getPolicyCardType());
        insBatchEntity.setPolicyCardType(policyCardType);
        String insuredCardType = CertificateTypeForCaseEnum.getCaseCodeByMsg(insBatchEntity.getInsuredCardType());
        insBatchEntity.setInsuredCardType(insuredCardType);
        // 处理学校类型
        String schoolType = insBatchEntity.getSchoolType();
        insBatchEntity.setSchoolType(SchoolTypeEnum.getCodeByMsg(schoolType));

        insBatchEntity.setHandleStatus(HandlerStatusEnum.NO_INS.getCode());
        //添加推广人信息
        ResponseEntity<GenericDataResponse<ManagerInfoVo>> response = registerCustomerService.queryPromoterByCustomerAccount(findCode, insBatchEntity.getPolicyMobile());
        if (GenericDataResponse.CODE_OK.equals(response.getBody().getCode()) && null != response.getBody().getData()) {
            ManagerInfoVo managerInfoVo = response.getBody().getData();
            insBatchEntity.setMarketerUserCode(managerInfoVo.getManagerUserCode());
            insBatchEntity.setMarketerName(managerInfoVo.getManagerName());
            insBatchEntity.setMarketerNo(managerInfoVo.getMarketerNo());
            insBatchEntity.setMarketerBranchCode(managerInfoVo.getBranchCode());
            insBatchEntity.setMarketerBranchName(managerInfoVo.getBranchName());
            insBatchEntity.setMarketerChannelCode(managerInfoVo.getChannelCode());
            insBatchEntity.setMarketerChannelName(managerInfoVo.getChannelName());
        } else {
            insBatchEntity.setMarketerUserCode(batchInsParam.getMarketerUserCode());
            insBatchEntity.setMarketerName(batchInsParam.getMarketerName());
            insBatchEntity.setMarketerNo(batchInsParam.getMarketerNo());
            insBatchEntity.setMarketerBranchCode(batchInsParam.getMarketerBranchCode());
            insBatchEntity.setMarketerBranchName(batchInsParam.getMarketerBranchName());
            insBatchEntity.setMarketerChannelCode(MarketerChannelCodeEnum.getNewCodeByCode(batchInsParam.getMarketerChannelCode()));
            insBatchEntity.setMarketerChannelName(batchInsParam.getMarketerChannelName());
        }
        insBatchEntity.setTimes(0);
        return insBatchEntity;
    }

    /**
     * 生成地区名对应的code
     *
     * @return
     */
    private Map<String, String> createAreaDate() {
        Map<String, String> regionMap = Maps.newHashMap();
        // 首先把 省市县 放入一个map 方便后边使用
        List<AreaInfoEntity> areaInfoEntities = areaInfoEntityMapper.selectAll();

        for (AreaInfoEntity areaInfoEntity : areaInfoEntities) {
            if (areaInfoEntity != null) {
                if ("1".equals(areaInfoEntity.getLevel())) {
                    regionMap.put(areaInfoEntity.getName(), areaInfoEntity.getCode());
                } else {
                    String name = areaInfoEntity.getName();
                    String parentCode = areaInfoEntity.getParentCode();
                    //这块使用 市或区名称_父编码 做key
                    regionMap.put(name + "_" + parentCode, areaInfoEntity.getCode());
                }

            }
        }
        return regionMap;
    }

    public ResponseEntity retryIns(String id) {
        String findCode = "RetryIs_" + System.currentTimeMillis();
        // 根据id 查询批量表  拿到数据 去拼报文  和 批量的是一样的
        InsBatchEntity insBatchEntity = new InsBatchEntity();
        insBatchEntity.setId(Long.valueOf(id));
        insBatchEntity = insBatchEntityMapper.selectByPrimaryKey(insBatchEntity);
        try {
            batchCreateInsOrder(findCode, insBatchEntity);
        } catch (Exception e) {
            log.info("{}重试ID为：{}的线下批量投保出错", findCode, id);
            return GenericDataResponse.errorWithMsg("重试投保出错!");
        }
        return GenericDataResponse.ok();
    }

    /**
     * 投保
     */
    public void sendMessageToIns(List<InsBatchEntity> insBatchEntityList) {
        for (InsBatchEntity insBatchEntity : insBatchEntityList) {
            String findCode = "BATCH_INS_" + insBatchEntity.getInsuredCardNo();
            try {
                batchCreateInsOrder(findCode, insBatchEntity);
            } catch (Exception e) {
                log.error("{} 下载出错，insBatchEntity 表id：{}", findCode, insBatchEntity.getId(), e);
                updateHandleStatusById(insBatchEntity.getId(), HandlerStatusEnum.FAIL_INS, insBatchEntity.getTimes() + 1);
            }
        }
    }

    /**
     * @param findCode
     * @param insBatchEntity
     * @throws Exception
     */
    private void batchCreateInsOrder(String findCode, InsBatchEntity insBatchEntity) throws Exception {
        String detailFindCode = findCode + "_" + insBatchEntity.getId();
        // 首先查看投保人是否注册。已注册，获取code，直接投保；未注册，先注册后获取code，再次投保。
        String holderCode = getHolderCode(detailFindCode, insBatchEntity);
        if (StringUtils.isBlank(holderCode)) {
            throw new Exception("投保用户注册失败");
        }
        //重复投保校验
        ConfirmPolicyQo confirmPolicyQo = new ConfirmPolicyQo();
        confirmPolicyQo.setCardId(insBatchEntity.getInsuredCardNo());
        confirmPolicyQo.setProductCode(insBatchEntity.getProCode());
        confirmPolicyQo.setChannelCode("edu");
        confirmPolicyQo.setStartDate(insBatchEntity.getStartYear());
        String confirmPolicyStr = JSON.toJSONString(confirmPolicyQo);
        log.info("{}重复投保校验,入参：{}", findCode, confirmPolicyStr);
        ResponseData confirmPolicyRes = wxbService.repeatInsurance(confirmPolicyQo);
        log.info("{}重复投保校验,出参：{}", findCode, JSON.toJSONString(confirmPolicyRes));
        if (GenericResponse.CODE_OK.equals(confirmPolicyRes.getCode())
                && null != confirmPolicyRes.getData()
                && !CollectionUtils.isEmpty((List) confirmPolicyRes.getData())) {
            //修改失败状态-重复的被保人
            updateHandleStatusById(insBatchEntity.getId(), HandlerStatusEnum.REPETITION_INS, insBatchEntity.getTimes() + 1);
            return;
        }

        //生成投保信息
        TbParamVO tbParamVO = createTbParamVO(insBatchEntity, holderCode);
        // 去调投保接口
        String paramJson = JsonUtils.toJson(tbParamVO);
        log.info("{} 生成的投保入参：{}", detailFindCode, paramJson);


        ResponseEntity<GenericDataResponse<Map<String, Object>>> genericDataResponseResponseEntity = insOrderClient.submitOrder(paramJson);
        GenericDataResponse<Map<String, Object>> body = genericDataResponseResponseEntity.getBody();
        String code = body.getCode();
        log.info("{} 调用投保接口出参：{}", detailFindCode, JsonUtils.toJson(genericDataResponseResponseEntity));
        if (GenericDataResponse.CODE_OK.equals(code)) {
//            //获得 保费
            Map<String, Object> data1 = (Map<String, Object>) body.getData().get("body");
            List<Object> information = (List<Object>) data1.get("applicationForms");
            String orderNo = (String) (((Map<String, Object>) data1.get("order"))).get("code");
            Map<String, Object> data2 = (Map<String, Object>) information.get(0);
            String prem = ((Map<String, Object>) data2.get("information")).get("prem").toString();
            String tbNo = (String) ((Map<String, Object>) data2.get("information")).get("applicationFormCode");
//
            insBatchEntity.setPrem(prem);
            insBatchEntity.setTbNo(tbNo);
            insBatchEntity.setOrderNo(orderNo);
            insBatchEntity.setConfirmStatus(ConFirmStatusEnum.DEFAULT.getCode());
            insBatchEntity.setHandleStatus(HandlerStatusEnum.SUCCESS_INS.getCode());
            //投保成功后，记录次数为0
            insBatchEntity.setTimes(0);
            insBatchEntityMapper.updateByPrimaryKeySelective(insBatchEntity);
        } else if ("9999".equals(code)) {
            //修改失败状态
            updateHandleStatusById(insBatchEntity.getId(), HandlerStatusEnum.FAIL_INS, insBatchEntity.getTimes() + 1);
        } else {
            //修改超时状态
            updateHandleStatusById(insBatchEntity.getId(), HandlerStatusEnum.OVER, insBatchEntity.getTimes() + 1);
        }
    }

    public void updateHandleStatusById(Long id, HandlerStatusEnum handlerStatusEnum, Integer times) {
        InsBatchEntity update = new InsBatchEntity();
        update.setId(id);
        update.setHandleStatus(handlerStatusEnum.getCode());
        update.setTimes(times);
        insBatchEntityMapper.updateByPrimaryKeySelective(update);
    }

    public void updateConfirmStatusById(Long id, ConFirmStatusEnum conFirmStatusEnum, Integer times) {
        InsBatchEntity update = new InsBatchEntity();
        update.setId(id);
        update.setConfirmStatus(conFirmStatusEnum.getCode());
        update.setTimes(times);
        insBatchEntityMapper.updateByPrimaryKeySelective(update);
    }

    /**
     * 生成投保信息
     *
     * @param insBatchEntity
     * @return
     */
    private TbParamVO createTbParamVO(InsBatchEntity insBatchEntity, String holderCode) {

        // 遍历集合数据  组装调用  远程接口的报文 TbParamVO
        TbParamVO tbParamVO = new TbParamVO();
        tbParamVO.setEntryType("01");
        tbParamVO.setSource("00");
        tbParamVO.setOperator(insBatchEntity.getUserCode());// 操作人员编码   前端传过来
        List<ContextApplicationForm> applicationForms = Lists.newArrayList();

        ContextApplicationForm contextApplicationForm = new ContextApplicationForm();

        /**
         * 投保单信息   可以用 liangtf
         */
        contextApplicationForm = createInformation(insBatchEntity, contextApplicationForm);

        /**
         * 投保人信息
         */
        contextApplicationForm.setPolicyHolder(createHolder(insBatchEntity, holderCode));
        /**
         * 被保险人信息
         */
        contextApplicationForm.setInsureds(Lists.newArrayList(createContextInsured(insBatchEntity)));

        /**
         * 推广人员信息
         */
        if (StringUtils.isNotBlank(insBatchEntity.getMarketerUserCode())) {
            ContextAgent agent = createContestAgent(insBatchEntity);
            contextApplicationForm.setAgents(Lists.newArrayList(agent));
        }

        /**
         * 险种信息
         */
        List<ContextRisk> risks = new ArrayList<>();
        ContextRisk contextRisk = new ContextRisk();
        contextRisk = createContextRisk(insBatchEntity, contextRisk);

        risks.add(contextRisk);
        contextApplicationForm.setRisk(risks);

        applicationForms.add(contextApplicationForm);

        tbParamVO.setApplicationForms(applicationForms);
        return tbParamVO;
    }

    /**
     * 注册或查询用户holderCode
     *
     * @param detailFindCode
     * @param insBatchEntity
     * @return
     */
    private String getHolderCode(String detailFindCode, InsBatchEntity insBatchEntity) {
        String holderCode = "";
        String policyMobile = insBatchEntity.getPolicyMobile();
        log.info("{} 通过投保人手机号 {}，查看是否注册。", detailFindCode, policyMobile);
        ResponseEntity<GenericDataResponse<Map<String, Object>>> edu = null;
        try {
            edu = userClient.queryPersonalUserAuthenInfo(policyMobile, "edu");
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        GenericDataResponse<Map<String, Object>> remoteMap = edu.getBody();
        Map<String, Object> data = remoteMap.getData();
        if (data == null) {
            log.info("{} 通过投保人手机号 {}，查看该手机并未注册。", detailFindCode, policyMobile);
            // 未注册,去注册
            // 组装参数
            PersonalUserAuthenParam personalUserAuthenParam = new PersonalUserAuthenParam();
            personalUserAuthenParam.setActualName(insBatchEntity.getPolicyName());
            personalUserAuthenParam.setAreaCode("");
            personalUserAuthenParam.setChannelCode("edu");
            personalUserAuthenParam.setDateOfBirth(insBatchEntity.getPolicyBirthday());
            personalUserAuthenParam.setDetailAddress("");
            personalUserAuthenParam.setEmail("");
            personalUserAuthenParam.setSex(insBatchEntity.getPolicySex());
            personalUserAuthenParam.setUserPhone(insBatchEntity.getPolicyMobile());
            List<OrgElementVO> orgElementVOList = Lists.newArrayList();
            OrgElementVO orgElementVO = new OrgElementVO("cardType", "证件类型"
                    , insBatchEntity.getPolicyCardType(), CertificateTypeForCaseEnum.getMsgCodeByCaseCode(insBatchEntity.getPolicyCardType()));
            orgElementVOList.add(orgElementVO);
            OrgElementVO orgElementVO2 = new OrgElementVO("cardNo", "证件号"
                    , "", insBatchEntity.getPolicyCardNo());
            orgElementVOList.add(orgElementVO2);
            personalUserAuthenParam.setOrgElementVOList(orgElementVOList);

            log.info("{} 调用渠道个人认证服务接口 userClient.personalUserAuthen 入参：", detailFindCode, JsonUtils.toJson(personalUserAuthenParam));
            // 去调接口

            ResponseEntity<GenericDataResponse<Map<String, Object>>> genericDataResponseResponseEntity = null;
            try {
                genericDataResponseResponseEntity = userClient.personalUserAuthen(personalUserAuthenParam);
            } catch (Exception e) {
                e.printStackTrace();
            }
            GenericDataResponse<Map<String, Object>> body = genericDataResponseResponseEntity.getBody();
            data = body.getData();
            // 可能会有问题。因为在用户中心，已注册用户，如果第二次投保时提交的信息与上次不一致，会再次进行注册，然后也注册不成功！！！，需要更换手机号才可以。
            if (data != null) {
                holderCode = (String) data.get("userCode");
            } else {
                log.info("{}用户注册失败，失败原因:{}", detailFindCode, JsonUtils.toJson(body));
            }
        } else {
            holderCode = (String) data.get("userCode");
        }
        return holderCode;
    }

    private ContextAgent createContestAgent(InsBatchEntity insBatchEntity) {
        ContextAgent agent = new ContextAgent();
        agent.setAgentName(insBatchEntity.getMarketerName());
        agent.setAgentCode(insBatchEntity.getMarketerUserCode());
        agent.setSmsAgentCode(insBatchEntity.getMarketerNo());
        agent.setBranchCode(insBatchEntity.getMarketerBranchCode());
        agent.setBranchName(insBatchEntity.getMarketerBranchName());
        agent.setChannelCode(insBatchEntity.getMarketerChannelCode());
        agent.setChannelName(insBatchEntity.getMarketerChannelName());
        return agent;
    }

    private ContextInsured createContextInsured(InsBatchEntity insBatchEntity) {
//        todo
        ContextInsured contextInsured = new ContextInsured();
        contextInsured.setType("01");
        String schoolprovname = insBatchEntity.getSchoolProvName();
//        String provinceCode = regionMap.get(schoolprovname);
        String provinceCode = insBatchEntity.getSchoolProvCode();
        contextInsured.setProvinceCode(provinceCode);
//        String cityCode = regionMap.get(insBatchEntity.getSchoolCityName() + "_" + provinceCode);
        String cityCode = insBatchEntity.getSchoolCityCode();
        contextInsured.setCityCode(cityCode);
        contextInsured.setBnfyOption("Y");
        contextInsured.setBirthday(insBatchEntity.getInsuredBirthday());
        contextInsured.setPhone(insBatchEntity.getInsuredMobile());
        contextInsured.setLicenceType(insBatchEntity.getInsuredCardType());
        contextInsured.setLicenceNo(insBatchEntity.getInsuredCardNo());
        contextInsured.setSex(insBatchEntity.getInsuredSex());
        contextInsured.setName(insBatchEntity.getInsuredName());
        contextInsured.setRelaToHolder(insBatchEntity.getInsuredPolicyRel());// todo  需要在excel中显示,可能需要处理
        contextInsured.setSchoolName(insBatchEntity.getInsuredSchool());
        contextInsured.setInsureYear(insBatchEntity.getInsYear());//  前端传过来
        contextInsured.setSchoolKind(insBatchEntity.getSchoolType());
        contextInsured.setGrade(insBatchEntity.getInsuredGrade());
        contextInsured.setClassAndGrade(insBatchEntity.getInsuredClass());
        return contextInsured;
    }

    private ContextHolder createHolder(InsBatchEntity insBatchEntity, String holderCode) {
        ContextHolder holder = new ContextHolder();
        holder.setHolderCode(holderCode);
        holder.setType("01");
        holder.setBirthday(insBatchEntity.getPolicyBirthday());
        holder.setPhone(insBatchEntity.getPolicyMobile());
        holder.setLicenceType(insBatchEntity.getPolicyCardType());
        holder.setLicenceNo(insBatchEntity.getPolicyCardNo());
        holder.setSex(insBatchEntity.getPolicySex());
        holder.setName(insBatchEntity.getPolicyName());
        return holder;
    }

    // todo
    private ContextApplicationForm createInformation(InsBatchEntity insBatchEntity, ContextApplicationForm information) {

        information.setChannelType("0001");
        information.setApplicationType("01");
        information.setEndDate(insBatchEntity.getEndYear());
        information.setCityCode(insBatchEntity.getSchoolCityCode());
        information.setRenewalTimes(0);
        String proCode = insBatchEntity.getProCode();
        String proName = ProNameToCodeEnum.getproductName(proCode);
        information.setProductName(proName);
        information.setPolicyKind("00");
        information.setCityName(insBatchEntity.getSchoolCityName());
        ProjectInfoEnum projectInfo = ProjectInfoEnum.getProjectInfo(proCode);
        information.setProjectCode(projectInfo.getProjectCode());
        information.setProjectName(projectInfo.getProjectName());
        information.setTerm(calculatedDays(insBatchEntity.getEndYear(), insBatchEntity.getStartYear()));
        information.setProductType("00");
        information.setCountyName(insBatchEntity.getSchoolAreaName());
        information.setIsRenewal("N");
        information.setProvinceCode(insBatchEntity.getSchoolProvCode());
        information.setChannalCode("edu");
        information.setBranchCode("JT0000");
        information.setBranchName("江泰保险经纪股份有限公司本部");
        information.setCountyCode(insBatchEntity.getSchoolAreaCode());
        information.setProductCode(proCode);
        information.setOriginalStatus("");//todo  貌似不用传 前端的投保报文 没有
        information.setProvinceName(insBatchEntity.getSchoolProvName());

        information.setStartDate(insBatchEntity.getStartYear());
        information.setRenewalLastPolicyNo("");
        information.setApplicationDate(DateUtils.converDate(new Date()));// 投保日期 默认当前
        return information;
    }

    /**
     * 险种对象
     *
     * @param insBatchEntity
     * @param contextRisk
     * @return
     */
    private ContextRisk createContextRisk(InsBatchEntity insBatchEntity, ContextRisk contextRisk) {

        String proCode = insBatchEntity.getProCode();
//        String proCode = ProNameToCodeEnum.getproductCode(proName);
        String proName = ProNameToCodeEnum.getproductName(proCode);
        String type = insBatchEntity.getProType();// A(1身故保障型 2医疗保障型)；B(1意外医保补充款 2全面保障款)
        String level = insBatchEntity.getProLevel();// 1  2 : 1基础版 2强化版 3完全版
        ContextRiskMap risk = null;
        if ("19PR979745".equals(proCode)) {// 济宁学平险
            risk = getRisk(InsuredRiskJson.JN_XPX);
            //险种
            Map<String, ContextRisk> contextRisks = risk.getContextRisks();
            // 我看着 济宁学平险  就只有一个产品类型
//            type = "19XZ804339";
            contextRisk = contextRisks.get("19XZ804339");
//             给限额赋值   1基础版 2强化版 3完全版
            setValueForLimit(contextRisk, level);
            contextRisk.setMainRiskCode(contextRisk.getRiskCode());
            contextRisk.setProgramCode(JNXPXProgramCodeEnum.getProgramCode("19PR979745", level));
        } else {// 云南学平险
            //老系统中有两种类型。限额都只有一种 。 1  身故保障型  2 医疗保障型
            risk = getRisk(InsuredRiskJson.YN_XPX);
            //险种
            Map<String, ContextRisk> contextRisks = risk.getContextRisks();
            /*
            if("1".equals(type)){
                type = "19XZ734571";
                contextRisk = contextRisks.get("19XZ734571");
            }else{
                type = "19XZ643399";
                contextRisk = contextRisks.get("19XZ643399");
            }
             */
            contextRisk = contextRisks.get(type);
            // 给限额赋值  YNXPXEnum
            setValueForYNXPXLimit(contextRisk);
            contextRisk.setMainRiskCode(contextRisk.getRiskCode());
            contextRisk.setProgramCode(YNXPXProgramCodeEnum.getProgramCode("19PR896371", type));
        }

        return contextRisk;
    }

    private void setValueForYNXPXLimit(ContextRisk contextRisk) {

        for (ContextDuty contextDuty : contextRisk.getDuties()) {

            for (ContextDutyLimit contextDutyLimit : contextDuty.getDutyLimits()) {
                if (contextDutyLimit != null) {
                    String code = contextDutyLimit.getCode();
                    Map<String, String> riskLimit = YNXPXEnum.getRiskLimit(code);
                    contextDutyLimit.setValue(riskLimit.get("value"));
                    contextDutyLimit.setValueCode(riskLimit.get("valueCode"));
                }
            }

        }
    }

    private void setValueForLimit(ContextRisk contextRisk, String productLevel) {

        for (ContextDuty contextDuty : contextRisk.getDuties()) {

            for (ContextDutyLimit contextDutyLimit : contextDuty.getDutyLimits()) {
                if (contextDutyLimit != null) {
                    String code = contextDutyLimit.getCode();
                    Map<String, String> riskLimit = JNXPXEnum.getRiskLimit(code, productLevel);
                    contextDutyLimit.setValue(riskLimit.get("value"));
                    contextDutyLimit.setValueCode(riskLimit.get("valueCode"));
                }
            }

        }
    }

    /**
     * 通过配置好的Json串得到RiskMap信息
     *
     * @return
     */
    public ContextRiskMap getRisk(String tempInfoStr) {

        RiskResponseEntity tempInfo = JSON.parseObject(tempInfoStr, RiskResponseEntity.class);

        ContextRiskMap contextRiskMap = ChangeUtils.toContextRiskMap(tempInfo.getRiskList());
        return contextRiskMap;
    }


    private Weekend<InsBatchEntity> getWeekendByBatchInsQueryParamVO(BatchInsQueryParamVO vo) {
        Weekend<InsBatchEntity> weekend = Weekend.of(InsBatchEntity.class);
        WeekendCriteria<InsBatchEntity, Object> criteria = weekend.weekendCriteria();
        if (!StringUtils.isEmpty(vo.getProCode())) {
            criteria.andEqualTo(InsBatchEntity::getProCode, vo.getProCode());
        }

        if (!StringUtils.isEmpty(vo.getPolicyName())) {
            criteria.andEqualTo(InsBatchEntity::getPolicyName, vo.getPolicyName());
        }

        if (!StringUtils.isEmpty(vo.getPolicyCardNo())) {
            criteria.andEqualTo(InsBatchEntity::getPolicyCardNo, vo.getPolicyCardNo());
        }

        if (!StringUtils.isEmpty(vo.getInsuredName())) {
            criteria.andEqualTo(InsBatchEntity::getInsuredName, vo.getInsuredName());
        }

        if (!StringUtils.isEmpty(vo.getInsuredCardNo())) {
            criteria.andEqualTo(InsBatchEntity::getInsuredCardNo, vo.getInsuredCardNo());
        }

        if (!StringUtils.isEmpty(vo.getPolicyNo())) {
            criteria.andEqualTo(InsBatchEntity::getPolicyNo, vo.getPolicyNo());
        }


        if (!StringUtils.isEmpty(vo.getStartDay())) {
            criteria.andGreaterThan(InsBatchEntity::getTbTime, vo.getStartDay());
        }

        if (!StringUtils.isEmpty(vo.getEndDay())) {
            criteria.andLessThan(InsBatchEntity::getTbTime, vo.getEndDay());
        }

        if (!StringUtils.isEmpty(vo.getHandleStatus())) {
            criteria.andEqualTo(InsBatchEntity::getHandleStatus, vo.getHandleStatus());
        }

        if (!StringUtils.isEmpty(vo.getStartYear())) {
            criteria.andGreaterThan(InsBatchEntity::getStartYear, vo.getStartYear());
        }

        if (!StringUtils.isEmpty(vo.getEndYear())) {
            criteria.andLessThan(InsBatchEntity::getStartYear, vo.getEndYear());
        }

//       省市县 查询被保险人
        if (!StringUtils.isEmpty(vo.getProvince())) {
            criteria.andEqualTo(InsBatchEntity::getSchoolProvCode, vo.getProvince());
        }
        if (!StringUtils.isEmpty(vo.getCity())) {
            criteria.andEqualTo(InsBatchEntity::getSchoolCityCode, vo.getCity());
        }
        if (!StringUtils.isEmpty(vo.getCountry())) {
            criteria.andEqualTo(InsBatchEntity::getSchoolAreaCode, vo.getCountry());
        }

        if (!StringUtils.isEmpty(vo.getOrderNo())) {
            criteria.andEqualTo(InsBatchEntity::getOrderNo, vo.getOrderNo());
        }

        weekend.setOrderByClause("tb_time DESC");

        return weekend;
    }


    public PageInfo<InsBatchEntity> searchBatchInsByExample(BatchInsQueryParamVO vo) {

        Page page = PageHelper.startPage(vo.getPn(), vo.getPs());
        List<InsBatchEntity> resultList = insBatchEntityMapper.selectByExample(getWeekendByBatchInsQueryParamVO(vo));
        PageInfo info = new PageInfo(page);
        info.setList(resultList);

        return info;

    }

    /**
     * 查询线下业务保单列表
     *
     * @param vo
     * @return
     * @throws Exception
     */
    public List<InsBatchEntity> getBatchInsList(BatchInsQueryParamVO vo) throws Exception {
        List<InsBatchEntity> resultList = insBatchEntityMapper.selectByExample(getWeekendByBatchInsQueryParamVO(vo));
        return resultList;
    }

    public InsBatchEntity searchInsById(Long id) {
        return insBatchEntityMapper.selectByPrimaryKey(id);
    }

    public void downInsTemplate(InsExcelEnum excelEnum, HttpServletResponse response, HttpServletRequest request) {
        InputStream inputStream = null;
        ServletOutputStream servletOutputStream = null;
        try {
            Resource resource = new ClassPathResource(excelEnum.getPath());
            response.setContentType(excelEnum.getContentType());
            response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate");
            response.addHeader("charset", "utf-8");
            response.addHeader("Pragma", "no-cache");
            String encodeName = URLEncoder.encode(excelEnum.getFilename(), StandardCharsets.UTF_8.toString());
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encodeName + "\"; filename*=utf-8''" + encodeName);

            inputStream = resource.getInputStream();
            servletOutputStream = response.getOutputStream();
            IOUtils.copy(inputStream, servletOutputStream);
            response.flushBuffer();
        } catch (Exception e) {
            log.error("模板下载异常{}", excelEnum);
        } finally {
            try {
                if (servletOutputStream != null) {
                    servletOutputStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
                System.gc();// 提示 进行垃圾回收
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}